<script setup lang="ts">
import { CloudScrollbar } from '../../scrollbar'
import { NodeEmptyTipsProvideKey } from '../config'
import { useSortable } from '../hooks/useSortable'
import { useWatchElement } from '../hooks/useWatchElement'
import type {
  CascaderNodeModel,
  CascaderRegionModel,
  NodeLevel
} from '../types'
import CardIcons from './CardIcons.vue'

type IEmits = {
  (event: 'node-click', node: CascaderNodeModel): void
}
const emit = defineEmits<IEmits>()

const level = defineModel<NodeLevel>('level', { required: true })
const nodes = defineModel<CascaderNodeModel[]>('nodes', { required: true })
const region = defineModel<CascaderRegionModel>('region', { required: true })
const emptyTips = inject(NodeEmptyTipsProvideKey)
const levelRowRef = ref<Element>()
const watchElRef = ref<Element>()
const scrollRef = ref<typeof CloudScrollbar>()
const wrapWidth = inject<Ref<number>>('cascadeWrapWidth')!

const isOverWidth = computed(() => {
  const nodeWidth = nodes.value.length
    ? nodes.value.length * 160 + (nodes.value.length - 1) * 8
    : 0
  return wrapWidth.value > nodeWidth
})

const handleScroll = (flag: 'left' | 'right') => {
  const left = scrollRef.value!.wrapRef.scrollLeft
  nextTick(() => {
    scrollRef.value?.scrollTo({
      left: flag === 'right' ? left + 168 : left - 168,
      behavior: 'smooth'
    })
  })
}

const currentData = computed(() => ({
  region: region.value.region_id,
  level: level.value
}))
useSortable({
  el: levelRowRef,
  nodes,
  current: currentData
})
useWatchElement({
  el: watchElRef,
  className: 'node-sortable-ghost',
  specifiedClass: 'is-target'
})
</script>
<template>
  <div ref="watchElRef" class="level-row__wrapper">
    <cloud-scrollbar ref="scrollRef" :native="true">
      <div
        v-if="!isOverWidth"
        class="suspension-btn-left"
        @click="handleScroll('left')">
        <i-icons-arrow />
      </div>
      <div
        ref="levelRowRef"
        :data-level-row="`${region.region_id}_${level}`"
        class="level-row"
        :class="{ 'is-empty': !nodes?.length }">
        <div v-if="!nodes?.length" class="level-empty__text">
          <template v-if="level === 1">
            {{ emptyTips?.level_1 }}
          </template>
          <template v-if="level === 2">
            {{ emptyTips?.level_2 }}
          </template>
        </div>
        <div
          v-for="node in nodes"
          :key="node.node_id"
          class="node-wrapper"
          :data-cdn-level="level"
          :data-cdn-node="node.node_id"
          :data-cdn-region="region.region_id"
          :class="{
            'node-wrapper__error': node.run_status === 4,
            'node-wrapper__warning': node.run_status === 2
          }"
          @click="emit('node-click', node)">
          <a-tooltip placement="top" effect="dark" trigger="hover">
            <template #content>
              <span class="text-sm/22px px-[5px] py-[3px]">{{
                node.node_name
              }}</span>
            </template>
            <div class="name">{{ node.node_name }}</div>
          </a-tooltip>
          <span class="ip mb-3">{{ node?.node_ip || '未知IP' }}</span>
          <card-icons :node="node" class="w-4" />
        </div>
      </div>
      <div
        v-if="!isOverWidth"
        class="suspension-btn-right"
        @click="handleScroll('right')">
        <i-icons-arrow class="rotate-180" />
      </div>
    </cloud-scrollbar>
  </div>
</template>

<style lang="less" scoped>
.cloud-scrollbar {
  padding: 0 var(--cdn-cascader-level-padding);
}
.level-row__wrapper {
  width: 100%;
  border-radius: var(--cdn-cascader-level-radius);
  background-color: var(--cdn-cascader-level-bg-color);
  border: 1px solid transparent;
  transition: background-color 0.3s ease;
  position: relative;
  .suspension-btn {
    @apply hidden;
  }
  &:hover {
    background-color: var(--cdn-cascader-level-hover-bg-color);
  }
  .suspension-btn-left {
    @apply z-2 absolute bg-white cursor-pointer top-1/2 rounded-4 left-2 w-8 h-8 flex-center my-auto border border-solid border-color-#EEEFF2;
    transform: translateY(-50%);
    box-shadow: 0px 4px 10px 0px rgba(29, 33, 41, 0.1);
  }
  .suspension-btn-right {
    @apply z-2 absolute bg-white cursor-pointer top-1/2 rounded-4 right-2 w-8 h-8 flex-center my-auto border border-solid border-color-#EEEFF2;
    transform: translateY(-50%);
    box-shadow: 0px 4px 10px 0px rgba(29, 33, 41, 0.1);
  }
  &::after {
    content: '';
    width: 48px;
    height: 100%;
    position: absolute;
    right: 0;
    top: 0;
    background: linear-gradient(
      270deg,
      #f7f8fa 22.05%,
      rgba(247, 248, 250, 0) 100%
    );
  }

  &.is-target {
    background-color: var(--cdn-cascader-level-row-target-bg) !important;
    border-color: var(--cdn-cascader-level-row-target-border-color) !important;
    .is-empty {
      justify-content: start;
      .level-empty__text {
        display: none;
        opacity: all 0.2s;
      }
    }
  }
}
.cdn-cascader.is-sortable .level-row__wrapper {
  background-color: var(--cdn-cascader-level-row-sortable-bg);
  border-color: var(--cdn-cascader-level-row-sortable-border-color);
}
.level-row {
  width: fit-content;
  min-width: 100%;
  height: var(--cdn-cascader-level-height);
  display: flex;
  padding: var(--cdn-cascader-level-padding) 0;
  align-items: center;
  gap: var(--cdn-cascader-level-items-gap);

  &.is-empty {
    justify-content: center;
  }

  .level-empty__text {
    font-size: 14px;
    color: var(--cdn-cascader-color-text-3);
    opacity: all 0.2s;
  }
  .node-wrapper {
    height: 100%;
    padding: var(--cdn-cascader-level-items-y-padding)
      var(--cdn-cascader-level-items-padding);
    width: var(--cdn-cascader-level-items-width);
    min-width: var(--cdn-cascader-level-items-width);
    border-radius: var(--cdn-cascader-level-items-radius);
    border: 1px solid var(--cdn-cascader-level-items-border-color);
    background-color: #fff;
    display: flex;
    flex-direction: column;
    cursor: pointer;
    &:hover {
      border-color: var(--cdn-cascader-level-row-target-border-color);
    }
    &__warning {
      border-color: #ffeecf;
      background: linear-gradient(
          180deg,
          rgba(255, 125, 0, 0.06) 0%,
          rgba(255, 125, 0, 0) 100%
        ),
        #fff;
    }
    &__error {
      border-color: #ffd7cf;
      background: linear-gradient(
          180deg,
          rgba(245, 63, 63, 0.06) 0%,
          rgba(245, 63, 63, 0) 100%
        ),
        #fff;
    }
    &.node-sortable-chosen {
      &.node-sortable-ghost {
        * {
          display: none;
          opacity: 0;
        }
        border-style: dashed;
        border-color: var(--cdn-cascader-level-items-ghost-border-color);
      }
      &.node-sortable-fallback {
        border-color: var(--cdn-cascader-primary);
        box-shadow: var(--cdn-cascader-level-items-fallback-shadow);
      }
    }

    .name,
    .ip {
      @apply !text-sm/22px w-full;
      display: inline-block;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .name {
      color: var(--cdn-cascader-color-text-1);
    }
    .ip {
      color: var(--cdn-cascader-color-text-2);
    }
  }
}
</style>
